import * as CONSTANT from '@/utils/constant.js';
import login from '@/common/login';
import useUserStore from '../stores/modules/user.js';
import _ from 'lodash';

class Request {
    constructor({ baseURL, timeout, maxRetries }) {
        this.baseURL = baseURL;
        this.timeout = timeout;
        this.maxRetries = maxRetries;
    }

    // 统一URL处理
    _formatUrl(url) {
        if (!url) throw new Error('URL是必需的参数');
        return url.startsWith('http') ? url : this.baseURL + url;
    }

    _safeParse(data) {
        if (typeof data) {
            try {
                data = JSON.parse(data);
            } catch (err) {}
        }
        return data;
    }

    // 统一选项处理
    _formatOptions(options, type) {
        const formatted = {
            ...options,
            url: this._formatUrl(options.url),
            data: options.data || {},
            header: options.header ?? {},
            timeout: options.timeout ?? this.timeout,
            _requestType: type
        };
        if (type === 'upload') {
            if (!options.filePath) throw new Error('filePath是必需的参数');
            formatted.name = options.name ?? 'file';
            formatted.fileType = options.fileType ?? 'image';
            formatted.timeout = options.timeout ?? 60 * 1000;
        }

        const user_store = useUserStore();
        const token = user_store.token;
        if (!_.isEmpty(token)) {
            formatted.header.token = token;
        }
        return formatted;
    }
    async request(options, maxRetries) {
        const formattedOptions = this._formatOptions(options, 'request');

        return new Promise((resolve, reject) => {
            uni.request({
                ...formattedOptions,
                success: result =>
                    this.requestDataEvent(resolve, reject, result, formattedOptions, maxRetries),
                fail: error => {
                    console.error('请求出错', error);
                    this.requestDataEvent(
                        resolve,
                        reject,
                        { statusCode: 0, error },
                        formattedOptions,
                        maxRetries
                    );
                }
            });
        });
    }

    async upload(options, maxRetries = this.maxRetries) {
        const formattedOptions = this._formatOptions(options, 'upload');
        console.log('formattedOptions', formattedOptions);

        return new Promise((resolve, reject) => {
            const uploadTask = uni.uploadFile({
                ...formattedOptions,
                success: result =>
                    this.requestDataEvent(resolve, reject, result, formattedOptions, maxRetries),
                fail: err => {
                    console.error('上传失败', err);
                    this.requestDataEvent(
                        resolve,
                        reject,
                        { statusCode: 0, error: err },
                        formattedOptions,
                        maxRetries
                    );
                }
            });

            if (options.onUploadProgress) {
                uploadTask.onProgressUpdate(options.onUploadProgress);
            }
        });
    }

    // 统一处理响应结果和重试逻辑
    requestDataEvent(resolve, reject, result, options, maxRetries) {
        const { statusCode } = result;

        // 网络错误或状态码错误时的重试逻辑
        if (statusCode === 0 || statusCode !== 200) {
            return this._handleError(resolve, reject, result, options, maxRetries);
        }
        // 成功响应处理
        return this._handleSuccess(resolve, reject, options, result, maxRetries);
    }

    // 重试
    _retryRequest(resolve, reject, options, maxRetries, data) {
        if (maxRetries > 0) {
            const retryMethod = options._requestType === 'upload' ? 'upload' : 'request';
            return this[retryMethod](options, maxRetries - 1)
                .then(resolve)
                .catch(reject);
        } else {
            return reject(data);
        }
    }

    // 处理错误和重试
    _handleError(resolve, reject, result, options, maxRetries) {
        if (maxRetries > 0) {
            return this._retryRequest(resolve, reject, options, maxRetries);
        }

        // 重试次数用尽
        const errorMsg =
            result.statusCode === 0
                ? result.error || '网络连接失败'
                : `网络错误: ${result.statusCode}`;

        if (result.statusCode !== 0) {
            uni.showToast({ title: '网络故障，请检查后重试', icon: 'none' });
        }

        return reject(errorMsg);
    }

    // 处理成功响应
    async _handleSuccess(resolve, reject, options, result, maxRetries) {
        // 业务状态码判断
        let { statusCode, data } = result;

        if (statusCode != 200) return reject(data);
        if (typeof data === 'string') {
            data = this._safeParse(data);
        }

        switch (data.code) {
            case 200:
                return resolve(data);
            case 201:
            case 101:
                await login();
                this._retryRequest(resolve, reject, options, maxRetries, data);
                break;
            default:
                console.log('------------->');
        }
    }

    get(options) {
        return this.request({ ...options, method: 'GET' }, this.maxRetries);
    }
    post(options) {
        return this.request({ ...options, method: 'POST' }, this.maxRetries);
    }
}

export default new Request({
    baseURL: CONSTANT.Request_URL,
    timeout: 1000 * 60 * 3,
    maxRetries: 0
});
